package xyz.riceball.security.authentication;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import xyz.riceball.framework.component.SpringContextHolder;
import xyz.riceball.usercore.entity.dto.LoginDTO;
import xyz.riceball.usercore.entity.po.RolePO;
import xyz.riceball.usercore.entity.po.UserPO;
import xyz.riceball.usercore.service.RoleService;
import xyz.riceball.usercore.service.UserService;

import java.util.ArrayList;
import java.util.List;


/**
 * <p>
 * 身份验证提供者
 * </p>
 *
 * @author xiaovcloud
 * @since 2022/4/25 00:18
 */
@Getter
@Setter
@Slf4j
public class RiceBallAuthenticationProvider implements AuthenticationProvider {

    private final UserService userService;
    private final RoleService roleService;
    private final PasswordEncoder passwordEncoder;

    public RiceBallAuthenticationProvider() {
        this.userService = SpringContextHolder.getBean(UserService.class);
        this.roleService = SpringContextHolder.getBean(RoleService.class);
        this.passwordEncoder = SpringContextHolder.getBean(PasswordEncoder.class);
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        if (authentication == null) {
            throw new AuthenticationServiceException("认证失败，authenticate信息为空!");
        }
        LoginDTO loginDTO = (LoginDTO) authentication.getCredentials();
        if (loginDTO == null || StrUtil.isEmpty(loginDTO.getUsername())) {
            throw new AuthenticationServiceException("认证失败，login信息为空!");
        }
        LambdaQueryWrapper<UserPO> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(UserPO::getUsername, loginDTO.getUsername());
        UserPO userPO = userService.getOne(wrapper);
        if (userPO == null) {
            throw new AuthenticationServiceException("账户不存在");
        }
        String encodedPassword = userPO.getPassword();

        if (!passwordEncoder.matches(loginDTO.getPassword(), encodedPassword)) {
            throw new AuthenticationServiceException("密码错误");
        }
        loginDTO.setUserId(userPO.getId());

        List<GrantedAuthority> authorities = getAuthorities(loginDTO.getUserId());
        log.info("用户[{}]登陆验证, 拥有角色：[{}]", loginDTO.getUsername(), authorities);
        RiceBallAuthenticationToken authenticationToken = new RiceBallAuthenticationToken(authorities, loginDTO);
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        return authenticationToken;
    }


    /**
     * 获取角色信息
     *
     * @param userId userId
     * @return authList
     */
    private List<GrantedAuthority> getAuthorities(String userId) {
        List<GrantedAuthority> authList = new ArrayList<>();
        List<RolePO> roleList = roleService.selectRoleByUserId(userId);
        roleList.forEach(role -> {
            authList.add(new SimpleGrantedAuthority(role.getCode()));
        });
        return authList;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(RiceBallAuthenticationToken.class);
    }
}
